package com.quantum.ui.component
{
	import com.quantum.ui.component.simpledatagrid.ISelectable;

	import flash.events.MouseEvent;
	import flash.ui.Keyboard;

	import mx.controls.AdvancedDataGrid;
	import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
	import mx.controls.listClasses.IListItemRenderer;
	import mx.core.ClassFactory;
	import mx.core.ISelectableList;
	import com.quantum.ui.component.simpledatagrid.LabelHeaderRenderer;

	public class SimpleDataGrid extends AdvancedDataGrid
	{

		public function SimpleDataGrid()
		{
			super();
			this.sortExpertMode=true;
			this.headerRenderer=new ClassFactory(LabelHeaderRenderer);
		}

		/**
		 * A function that will filter a item renderer as selection disabled in the datagrid.
		 * That means that you can perform an operation (click a button, a checkbox or a radio button
		 * on this item renderer or just simply click on this item renderer itself) but it won't
		 * trigger the event to make the row of this item renderer selected.
		 * The function will be set in following form:
		 * function(item:IListItemRenderer):Boolean;
		 * If the function return true, that means the item renderer will be filtered as disabled.
		 */
		public var itemRendererSelectionDisabledFunction:Function;

		/**
		 * A function that will filter a row as selection disabled in the datagrid.
		 * The function will be set in following form:
		 * function(data:Object):Boolean;
		 * If the function return true, that means the row containing the data will be filtered as disabled.
		 */
		public var rowDataSelectionDisabledFunction:Function;

		public var showItemHighlight:Boolean=true;

		public var showItemSelection:Boolean=true;

		public var showItemCaret:Boolean=true;

		public var loadingState:String="loaded";

		override protected function updateDisplayOfItemRenderer(r:IListItemRenderer):void
		{
			if (r && r.data)
			{
				var itemSelectable:Boolean=!disableRowData(r.data);
				if (r is ISelectable)
				{
					ISelectable(r).selectable=itemSelectable;
				}
				else
				{
					r.enabled=itemSelectable;
				}
			}
			super.updateDisplayOfItemRenderer(r);
		}

		protected function disableRowData(data:Object):Boolean
		{
			if (rowDataSelectionDisabledFunction != null)
			{
				return rowDataSelectionDisabledFunction(data);
			}
			return false;
		}

		protected function disableItemRenderer(item:IListItemRenderer):Boolean
		{
			if (itemRendererSelectionDisabledFunction != null)
			{
				return itemRendererSelectionDisabledFunction(item);
			}
			return false;
		}

		override protected function selectItem(item:IListItemRenderer, shiftKey:Boolean, ctrlKey:Boolean, transition:Boolean=true):Boolean
		{
			if (item && disableRowData(item.data))
			{
				return false;
			}
			return super.selectItem(item, shiftKey, ctrlKey, transition);
		}

		override protected function drawItem(item:IListItemRenderer, selected:Boolean=false, highlighted:Boolean=false, caret:Boolean=false, transition:Boolean=false):void
		{
			super.drawItem(item, selected && showItemSelection, highlighted && showItemHighlight, caret && showItemCaret, transition);

		}

		override protected function mouseEventToItemRenderer(event:MouseEvent):IListItemRenderer
		{
			var item:IListItemRenderer=super.mouseEventToItemRenderer(event);
			if (item && item.data && item.data is AdvancedDataGridColumn)
			{
				return item;
			}
			if (item && disableItemRenderer(item))
			{
				return null;
			}
			if (item && item.data && disableRowData(item.data))
			{
				return null;
			}
			return item;
		}

		override protected function moveSelectionVertically(code:uint, shiftKey:Boolean, ctrlKey:Boolean):void
		{
			var i:int;
			var newIndex:int;

			switch (code)
			{
				case Keyboard.UP:
					newIndex=getPreviousUnselectableIndex(caretIndex - 1);
					break;

				case Keyboard.DOWN:
					newIndex=getNextUnselectableIndex(caretIndex + 1);
					break;

				case Keyboard.HOME:
					newIndex=getFirstSelectableIndex();
					code=Keyboard.UP;
					break;

				case Keyboard.END:
					newIndex=getLastSelectableIndex();
					code=Keyboard.DOWN;
					break;

				case Keyboard.PAGE_UP:
					newIndex=Math.max(getFirstSelectableIndex(), getPreviousUnselectableIndex(caretIndex - (rowCount - 2)));
					code=Keyboard.UP;
					break;

				case Keyboard.PAGE_DOWN:
					newIndex=Math.min(getLastSelectableIndex(), getNextUnselectableIndex(caretIndex + (rowCount - 1)));
					code=Keyboard.DOWN;
					break;
			}

			if (newIndex > -1 && newIndex < collection.length)
			{
				caretIndex=newIndex;
				super.moveSelectionVertically(code, shiftKey, ctrlKey);
			}
		}

		private function getFirstSelectableIndex():int
		{
			var result:int=-1;

			for (var i:int=0; i < collection.length; i++)
			{
				if (!disableRowData(collection[i]))
				{
					result=i + 1;
					break;
				}
			}

			return result;
		}

		private function getLastSelectableIndex():int
		{
			var result:int=-1;

			for (var i:int=collection.length - 1; i > -1; i--)
			{
				if (!disableRowData(collection[i]))
				{
					result=i - 1;
					break;
				}
			}

			return result;
		}

		private function getPreviousUnselectableIndex(startIndex:int):int
		{
			var result:int=-1;

			for (var i:int=startIndex; i > -1; i--)
			{
				if (!disableRowData(collection[i]))
				{
					result=i + 1;
					break;
				}
			}

			return result;
		}

		private function getNextUnselectableIndex(startIndex:int):int
		{
			var result:int=collection.length;

			for (var i:int=startIndex; i < collection.length; i++)
			{
				if (!disableRowData(collection[i]))
				{
					result=i - 1;
					break;
				}
			}

			return result;
		}
	}
}